iT邦幫忙

2024 iThome 鐵人賽

DAY 14
0
Software Development

從Servlet到Spring MVC系列 第 14

Day13 Servlet - Absolute and relative path

  • 分享至 

  • xImage
  •  

前言

對於資源訪問與資源引用路徑沒弄清楚真的會有點混亂,希望透過這一天的梳理在未來就不會再有困惑了

0、創建module

請參考Day05創建module

案例建置

https://ithelp.ithome.com.tw/upload/images/20240928/20128084fa0WBmjsXt.png
index.html內容

<img src="static/imag/tomcat.png">

內容

<img src="../../../static/imag/tomcat.png">

protected.html內容

<img src="../../static/imag/tomcat.png">

AccessProtectedResourceServlet

@WebServlet("/AccessProtectResourceServlet")
public class AccessProtectResourceServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.getRequestDispatcher("WEB-INF/views/protected.html").forward(req, resp);
    }
}

一、前端相對路徑

  • 以當前資源的所在路徑去尋找目標資源
  • 相對路徑不以**/**開頭
  • http下使用的是url路徑,file協議下使用的是檔案路徑
  • 以**./**表示當前資源所在路徑,可以省略
  • 以**../**表示當前資源的上一層資源路徑

案例1訪問 index.html

https://ithelp.ithome.com.tw/upload/images/20240928/20128084RU4UjflTO5.png
你會發現他發送兩次請求,第一次訪問index.html,第二次取得圖片時相對路徑會依照第一次訪問資源路徑去取得圖片

  • 當前資源請求路徑:http://localhost:8080/MyWebApp/index.html
  • 當前資源:index.html
  • 當前資源所在路徑:http://localhost:8080/MyWebApp/
  • tomcat.png相對於index.html的路徑為:static/imag/tomcat.png
  • 所以請求圖片資源的路徑就會是當前資源路徑合併相對資源圖片路徑:http://localhost:8080/MyWebApp/static/imag/tomcat.png
    https://ithelp.ithome.com.tw/upload/images/20240928/201280848Vn0cohizB.png

案例2訪問 test.html

tomcat.png相對於test.html的路徑為:../../../static/imag/tomcat.png
https://ithelp.ithome.com.tw/upload/images/20240928/20128084JkSUh3UJIj.png

案例3訪問 protected.html

前一日有提到在WEB-INF下的頁面是受保護資源,需要透過Servlet請求轉法才能看到。此處如果以資料夾結構的思維可能會認為tomcat.png相對於protected.html的路徑而設置為../../static/imag/tomcat.png,而得到下面錯誤訊息
https://ithelp.ithome.com.tw/upload/images/20240928/20128084bvyPNDyeJm.png
正確來看應

  • 訪問資源為:AccessProtectResourceServlet
  • 訪問資源路徑為:http://localhost:8080/MyWebApp/
  • 正確tomcat.png相對訪問請資源路徑應為:static/imag/tomcat.png
    修改後測試
    https://ithelp.ithome.com.tw/upload/images/20240928/20128084VaV9M5e0l9.png

二、前端絕對路徑

以固定的路徑作為出發點尋找目標資源,不會依賴當前訪問資源路徑

  • 以/開頭
  • 不同的網站上下文(Application Context)出發點會不一致,以本例來說指的是MyWebApp
    所以index.html、test.html、protected.html路徑只要寫成以下
<img src="/static/imag/tomcat.png">

三、前端路徑小結

相對路徑

缺點:目標資源會受當前資源路徑影響,不同的位置相對路徑寫法就不同

絕對路徑

優點:絕對路徑寫法一致
缺點:絕對路徑需要寫網站上下文(本例是MyWebApp),若有異動則需要將所有訪問資源絕對路徑進行修改。html有base標籤可以簡化這個部分,訪問資源時會幫你將頁面中每一個路徑加上/MyWebApp/變成/MyWebApp/static/imag/tomcat.png

<head>
    <base href="/MyWebApp/"/>
</head>
<img src="static/imag/tomcat.png">
<img src="static/imag/tomcat.png">

四、後端相對路徑

案例建置

ServletA

@WebServlet("/x/y/z/ServletA")
public class ServletA extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("訪問ServletA");

        resp.sendRedirect("ServletB");
    }
}

ServletB

@WebServlet("/ServletB")
public class ServletB extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse res){
        System.out.println("訪問ServletB");
    }
}

Sendirect - 相對路徑

  • 當前資源:ServletA
  • 訪問資源路徑為:http://localhost:8080/MyWebApp/x/y/z/
  • 重導資源相對訪問資源路徑為:../../../ServletB
    結果,觀察訪問ServletA的response訪問的location
    https://ithelp.ithome.com.tw/upload/images/20240928/20128084Kfv5dy1fyp.png

Sendirect - 絕對路徑

@WebServlet("/x/y/z/ServletA")
public class ServletA extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("訪問ServletA");
        //絕對路徑
        resp.sendRedirect("/MyWebApp/ServletB");
    }
}

https://ithelp.ithome.com.tw/upload/images/20240928/201280849s4cg3tQwo.png

Dispatcher - 絕對路徑

請求轉發為Server端行為所以client端不會知道,網址不變

@WebServlet("/x/y/z/ServletA")
public class ServletA extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("訪問ServletA");
        req.getRequestDispatcher("../../../ServletB").forward(req,resp);
    }
}

https://ithelp.ithome.com.tw/upload/images/20240928/20128084J9ztnx78Mx.png

Dispatcher - 絕對路徑

絕對路徑不需要添加網站上下文(MyWebApp)

@WebServlet("/x/y/z/ServletA")
public class ServletA extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("訪問ServletA");
        req.getRequestDispatcher("/ServletB").forward(req,resp);
    }
}

https://ithelp.ithome.com.tw/upload/images/20240928/20128084fhY9f965lQ.png

五、後端路徑小結

絕對路徑以/開頭,相對路徑相對於當前訪問資源,所以以當前訪問資源路徑為起始點。比較特別的是請求轉發的絕對路徑是不需要添加網站上下文(MyWebApp),故請求轉發的/代表的是http://localhost/MyWebApp/。

六、總結

是不是有被路徑問題繞得暈頭轉向了呢,問題就在於有網站上下文這個問題,所以把網站上下文設定為/並且資源路徑設為絕對路徑的方式是比較好的實踐方式,網站上下文的目的是為了區分在Application Server上有多個項目佈署,但實際上我們的Application Server只會掛載一個Web項目,未來的範例專案我們都會省去MyWebApp喔
https://ithelp.ithome.com.tw/upload/images/20240928/20128084pajttO77CW.png

Reference


上一篇
Day12 Servlet - Garbled characters
下一篇
Day14 Servlet - Cookie and Session
系列文
從Servlet到Spring MVC36
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言